﻿using MengCC.Common.Serialize;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Text.Json.Serialization;
using MengCC.Common;
using MengCC.Common.IO;

namespace MengCC.Core.Plugins
{
    public class PluginManager
    {
        private static List<Plugin> plugins;
        private string pluginRootDir;
        private PluginDowloader pluginDowloader;

        static PluginManager()
        {
            plugins = new List<Plugin>();

        }
       
        public PluginManager(string pluginRootDir)
        {
            this.pluginRootDir = pluginRootDir;
            pluginDowloader = new PluginDowloader(Path.Combine(pluginRootDir, "TempPlugins"));
        }

        /// <summary>
        /// 载入插件
        /// </summary>
        public void LoadPlugins()
        {
            pluginDowloader.Clear();
            plugins.Clear();
            var pluginDir = Path.Combine(pluginRootDir, "Plugins");
            if (!Directory.Exists(pluginDir)) Directory.CreateDirectory(pluginDir);
            var pluginDirs = Directory.GetDirectories(pluginDir);
            //遍历插件目录,解析插件配置
            foreach (var dir in pluginDirs)
            {
                try
                {
                    var configPath = Path.Combine(dir, "config.json");
                    if (!File.Exists(configPath)) continue;
                    var plugin = JsonConvert.DeserializeObject<Plugin>(File.ReadAllText(configPath, Encoding.Default));
                    plugin.Path = dir.Replace(pluginDir, "").Trim('\\');
                    plugin.Name = $"{plugin.Name}_{plugin.Platform}";
                    plugin.Id = plugin.Name;
                    if (plugin != null) plugins.Add(plugin);
                }
                catch (Exception ex)
                {
                    //
                }
            }
        }

        /// <summary>
        /// 根据插件类型获取插件
        /// </summary>
        /// <param name="pluginType"></param>
        /// <returns></returns>
        public List<Plugin> GetPluginsByType(Plugin.PluginEnum pluginType)
        {
            return plugins.Where(p => p.Types.Contains(pluginType.ToString())).ToList();
        }
        /// <summary>
        /// 获取所有本地插件
        /// </summary>
        /// <returns></returns>
        public List<Plugin> GetAllPlugins()
        {
            return plugins;
        }
        /// <summary>
        /// 根据插件id获取插件
        /// </summary>
        /// <param name="pluginId"></param>
        /// <returns></returns>
        public Plugin GetPluginById(string pluginId)
        {
            return plugins.Where(p => p.Id.Equals(pluginId)).FirstOrDefault();
        }

        

        /// <summary>
        /// 获取命令
        /// </summary>
        /// <param name="plugin"></param>
        /// <param name="pluginContext"></param>
        /// <returns></returns>
        public string  GetDotnetCommand(Plugin plugin,string args)
        {
            return $"{Path.Combine(pluginRootDir, "Plugins", plugin.Path, plugin.EntryLib)} {args}";
        }
        /// <summary>
        /// 获取命令
        /// </summary>
        /// <param name="plugin"></param>
        /// <param name="pluginContext"></param>
        /// <returns></returns>
        public string GetFrameworkCommand(Plugin plugin)
        {
            return $"{Path.Combine(pluginRootDir, "Plugins", plugin.Path, plugin.EntryLib)}";
        }


        /// <summary>
        /// 更新 插件
        /// </summary>
        public void UpdatePlugins()
        {
            var tempDir = Path.Combine(pluginRootDir, "TempPlugins");
            if (!Directory.Exists(tempDir)) return;
            foreach (var item in Directory.GetDirectories(tempDir))
            {
                var pluginDir = item.Replace("TempPlugins", "Plugins");
                //如果同名插件存在，则移除再剪切
                if (Directory.Exists(pluginDir)) DirectoryHelper.RemoveAll(pluginDir);
                Directory.Move(item, pluginDir);
            }
        }
        /// <summary>
        /// 删除插件
        /// </summary>
        /// <param name="pluginName"></param>
        public void RemovePlugin(string pluginName, string platform)
        {
            var pluginDir =Path.Combine(pluginRootDir, "Plugins",$"{pluginName}_{platform}");
            if (Directory.Exists(pluginDir)) DirectoryHelper.RemoveAll(pluginDir);
            LoadPlugins();
        }


        /// <summary>
        /// 根据地址载入插件配置列表
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public List<PluginDownloadConfig> LoadPluginDownloadList(string pluginReposityrUrl)
        {
            var result = new List<PluginDownloadConfig>();
            try
            {
                var gitDownloader = new GitDownloader();
                var storePath = Path.Combine(pluginRootDir, "plugins_config");
                DirectoryHelper.RemoveAll(storePath);
                gitDownloader.Download(storePath, pluginReposityrUrl, "master");
                var configPath = Path.Combine(storePath, "plugins.xml");
                if (!File.Exists(configPath)) return result;
                var availablePlugins = XmlConvert.DeserializeObject<List<PluginDownloadConfig>>(File.ReadAllText(configPath, Encoding.UTF8));
                //过滤本地已安装的插件
                var pluginsStr = string.Join(",", plugins.Select(p => $"{p.Name}_{p.Version}"));
                availablePlugins = availablePlugins.Where(ap => !pluginsStr.Contains($"{ap.Name}_{ap.Platform}_{ap.Version}")).ToList();
                return availablePlugins;
            }
            catch (Exception)
            {
                return result;
            }
        }
        /// <summary>
        /// 下载插件
        /// </summary>
        /// <param name="pluginDownloadConfig"></param>
        public void DownloadPlugin(PluginDownloadConfig pluginDownloadConfig)
        {
            pluginDowloader.AddTask(pluginDownloadConfig);
        }
        /// <summary>
        /// 获取下载是否完成
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public bool GetPluginDownloadState(string name,string platform)
        {
            return pluginDowloader.HasDownloaded($"{name}_{platform}");
        }
    }
}
